home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio.more / old / USeqGopher.inc.p < prev    next >
Text File  |  1996-07-05  |  52KB  |  1,931 lines

  1. { USeqGopher.inc.p  }
  2. { copyright by d.g.gilbert, 1992 for SeqApp. }
  3.  
  4. {
  5.             This code is Copyright (C) 1992 by D.G. Gilbert.
  6.             All Rights Reserved.
  7.  
  8.             You may use this code for your personal use, to provide a non-profit
  9.             service to others, or to use as a test platform for a commercial
  10.             implementation. 
  11.  
  12.             You may NOT use this code in a commercial product, nor to provide a
  13.             commercial service, nor may you sell this code without express
  14.             written permission of the author.  
  15.             
  16.             gilbertd@bio.indiana.edu 
  17.             Biology Dept., Indiana University, Bloomington, IN 47405 
  18. }
  19.  
  20. {$S USeqGopher }
  21.  
  22.  
  23.  
  24. CONST
  25.         cOpenGopher = 25;  {!? this is used also in SeqApp main -- need public, other way ?}
  26.         cNewGopherLink    = 2240;
  27.         cEditGopher    = 2241;
  28.     
  29.         kGopherWindID     = 2201;             
  30.         kGopherStyleID     = 2202;
  31.         kGopherPrefsID     = 2203;
  32.         kGopherSearchID    = 2204;
  33.         kGopherViewID     = 2205;
  34.         
  35.         kServerEditDlog = 2242;
  36.         
  37.         mPrefFont = 1005;    { for prefs }
  38.         mPrefSize = 1004;
  39.         mParentMenus = 1006;
  40.         
  41.         kGopherScrapType= kGopherFileType;
  42.         kSAppSig                = 'SApp';                { copied from USequence.p }
  43.         kGopherDocSig     = kSAppSig;
  44.         kGopherNoname     = '•noName';
  45.  
  46. VAR
  47.         gItemColor     : RGBColor;
  48.         gItemStyle    : TextStyle;
  49.         gIconSize        : integer;
  50.         gShowKind, gShowPath, gShowHost, gShowPort, gShowDate, gShowSize,
  51.         gListUnknowns,     gAllowLinkEdits, gUseServerMap    : boolean;
  52.         gWantFonts, gSameWindow    : boolean;
  53.         gNumWindows    : integer;
  54.         gSaveclip        : RgnHandle;
  55.  
  56.         gUseDig            : boolean;
  57.         gDigFolder    : Str63;
  58.         gDigVol            : Integer;
  59.         gDigDirID        : Longint;
  60.         
  61.         gLastParentList: TGopherList;
  62.         gPoppingMenu: Boolean;
  63.     
  64. FUNCTION AppFileToList( af: AppFile): TList;
  65. VAR  tf: TFile; tl: TList;
  66. BEGIN
  67.   NEW( tf); FailNIL( tf);
  68.     FailOSErr( tf.SpecifyWithTrio( af.vRefNum, 0, af.fName));
  69.     tl:= NewList; FailNIL( tl);
  70.     tl.InsertLast(tf);
  71.     AppFileToList:= tl;
  72. END;
  73.  
  74.  
  75.  
  76. {    TGopherDocument -------------------------- }
  77.  
  78.         
  79. PROCEDURE TGopherDocument.IGopherDocument( linkData: Handle; title: StringHandle; 
  80.                                                              parentMenu: TGopher; itsFile: TFile);
  81. var 
  82.         aRefNum, i: Integer;
  83.         aGopherList: TGopherList;
  84.         path: Handle;
  85.         
  86.         PROCEDURE copyParent( aPar: TGopher);
  87.         BEGIN
  88.             aPar:= TGopher(aPar.Clone);
  89.             aPar.fOwnerList:= fParentList;
  90.             fParentList.InsertLast( aPar);
  91.         END;
  92.                 
  93. BEGIN
  94.     fStatus:= NIL;
  95.     fDropBut:= NIL;
  96.     fGopherView:= NIL; 
  97.     fLongTitle:= NIL;
  98.     fParentList:= NIL;
  99.     fParentPopup:= NIL;
  100.     NEW( aGopherList);
  101.     FailNIL( aGopherList);
  102.     fParentList:= aGopherList;
  103. {-    gPoppingMenu:= FALSE;}
  104.     
  105.     IF parentMenu<>NIL THEN BEGIN
  106.         parentMenu:= TGopher(parentMenu.Clone);
  107.         parentMenu.fOwnerList:= fParentList;
  108.         END
  109.     ELSE BEGIN
  110.         NEW( parentMenu);
  111.         FailNIL( parentMenu);
  112.         path:= NewHandle(0);
  113.         parentMenu.IGopher( 'local', path, kGopherNoname, 0, '1'); 
  114.         path:= DisposeIfHandle(path);
  115.         END;
  116.     fParentList.IGopherList(gListUnknowns, gUseServerMap, gUseDig,
  117.                                                     gDigVol, gDigDirID, parentMenu);
  118.     
  119.     IF (gLastParentList <> NIL) THEN BEGIN 
  120.         gLastParentList.Each( copyParent);    
  121.         gLastParentList.Free; {we made this a new list, but objects are not dupped}
  122.         gLastParentList:= NIL;
  123.         END;
  124.     fParentList.InsertFirst( parentMenu);
  125.     
  126.     NEW(aGopherList);    
  127.     FailNIL( aGopherList);
  128.     fGopherList:= aGopherList;
  129.  
  130.     {- PushMenu( linkData, title, parentMenu); }
  131.         
  132.     fGopherList.IGopherList(gListUnknowns, gUseServerMap, gUseDig,
  133.                                                     gDigVol, gDigDirID, parentMenu);
  134.     IF (linkData<>NIL) THEN fGopherList.ReadLinks( linkData);
  135.     IF (title<>NIL) THEN FailOSErr( HandToHand( Handle( title)));
  136.     fLongTitle:= title;
  137.             
  138.     IFileBasedDocument(itsFile, kGopherFileType);
  139. END;
  140.  
  141.  
  142. PROCEDURE TGopherDocument.PushMenu( linkData: Handle; title: StringHandle; 
  143.                                                                          parentMenu: TGopher);
  144. {! this is always failing, as if linkData, title where NIL or mangled...}
  145. BEGIN
  146.     {- FreeData; }  
  147.     if (fLongTitle<>NIL) THEN DisposHandle(Handle(fLongTitle));  fLongTitle:= NIL;
  148.     IF (fGopherList<>NIL) THEN fGopherList.FreeAll;  {empty but valid for new data }
  149.  
  150.     IF parentMenu<>NIL THEN BEGIN
  151.         parentMenu:= TGopher(parentMenu.Clone);
  152.         parentMenu.fOwnerList:= fParentList;
  153.         fParentList.InsertFirst( parentMenu);    
  154.         IF (fParentPopup<>NIL) THEN
  155.             AppendMenu( fParentPopup.GetMenuHandle, parentMenu.ShortName);
  156.         END;
  157.     fGopherList.fParentMenu:= parentMenu;
  158.  
  159.     IF (linkData<>NIL) THEN fGopherList.ReadLinks( linkData);
  160.     IF (title<>NIL) THEN FailOSErr( HandToHand( Handle( title)));
  161.     fLongTitle:= title;
  162.  
  163.     {- ShowReverted; }
  164.     fGopherView.IGopherView( fGopherList); 
  165.   fGopherView.ForceRedraw;
  166. END;
  167.  
  168.  
  169. PROCEDURE TGopherDocument.PopMenu( uplevels: integer);
  170. VAR
  171.     fi        : FailInfo;
  172.     parentMenu: TGopher;
  173.     flag, notFound    : boolean;
  174.     i    : integer;
  175.     
  176.     PROCEDURE HdlGopherFailure(error: OSErr; message: LONGINT);
  177.     BEGIN
  178.         gSameWindow:= flag;
  179.     END;
  180.  
  181.     PROCEDURE checkOpenDocs( aDoc: TDocument);
  182.     VAR     docList: TGopherList;  docOwner: TGopher;
  183.     BEGIN
  184.         IF Member( TObject(aDoc), TGopherDocument) THEN BEGIN 
  185.             docList:= TGopherDocument(aDoc).fParentList;
  186.             {^^^ need to fix this to find '• Home' base document...}
  187.             IF (docList<>NIL) THEN BEGIN
  188.                 docOwner:= TGopher(docList.First);
  189.                 IF (docOwner<>NIL) & parentMenu.Equals(docOwner) THEN BEGIN
  190.                     notFound:= FALSE;
  191.                     TWindow(aDoc.fWindowList.First).Select;  
  192.                     END;
  193.                 END;
  194.             END;
  195.     END;
  196.  
  197. BEGIN
  198.     parentMenu:= TGopher( fParentList.At( uplevels));
  199.     (******
  200.     --- IF (gSameWindow) THEN ---
  201.     parentMenu:= NIL;
  202.     while (uplevels > 1) & (fParentList.GetSize > 1) DO BEGIN
  203.         fParentList.Delete(parentMenu);        
  204.         IF (fParentPopup<>NIL) THEN DelMenuItem( fParentPopup.GetMenuHandle, 1);
  205.         parentMenu:= TGopher( fParentList.First);
  206.         uplevels:= uplevels-1;
  207.         end;
  208.     ****)
  209.     IF (parentMenu<>NIL) THEN BEGIN
  210.         { !! We should look thru list of open docs for this parent before we DoGopher...}
  211.         notFound:= TRUE;
  212.         gApplication.ForAllDocumentsDo(checkOpenDocs); 
  213.         IF notFound THEN BEGIN
  214.             {- flag:= gSameWindow; gSameWindow:= TRUE;
  215.             CatchFailures(fi, HdlGopherFailure);
  216.             }
  217.             gLastParentList:= TGopherList(NewList);
  218.             FailNIL(gLastParentList);
  219.             FOR i:= uplevels+1 TO fParentList.GetSize DO
  220.                 gLastParentList.InsertLast( fParentList.At( i));
  221.             gPoppingMenu:= TRUE; {!@ damn nother global msg, this is getting messy }
  222.             DoGopher( parentMenu);
  223.             gPoppingMenu:= FALSE;
  224.             {- 
  225.             Success(fi);
  226.             gSameWindow:= flag; 
  227.             }
  228.             END;
  229.         END;
  230. END;
  231.  
  232.  
  233. PROCEDURE TGopherDocument.ShowParentMenu;
  234. BEGIN
  235.     fParentPopup.ViewEnable( TRUE, kDontRedraw);
  236.     fParentPopup.SetCurrentItem(1, kDontRedraw);
  237.     {- fParentPopup.AdjustBotRight;}
  238.     fParentPopup.Show( TRUE, kRedraw);
  239. END;
  240.     
  241. PROCEDURE TGopherDocument.HideParentMenu;
  242. BEGIN
  243.     IF (fParentPopup.IsShown) THEN BEGIN
  244.         fParentPopup.Show( FALSE, kRedraw);
  245.         fParentPopup.ViewEnable( FALSE, NOT kRedraw);
  246.         END;
  247. END;
  248.  
  249.  
  250. PROCEDURE TGopherDocument.DoGopher( aGopher: TGopher);
  251. VAR  
  252.         fi        : FailInfo;
  253.         gopherCommand, i : integer;
  254.         afList: TList;
  255.         
  256.     PROCEDURE HdlGopherFailure(error: OSErr; message: LONGINT);
  257.     BEGIN
  258.         UpdateStatus;
  259.         gopherCommand:= cNoCommand;
  260.     END;
  261.     
  262. BEGIN
  263.     IF (aGopher<>NIL) THEN BEGIN
  264.         If gPoppingMenu THEN HideParentMenu;
  265.         UpdateStatus;
  266.         CatchFailures(fi, HdlGopherFailure);
  267.         gopherCommand:= aGopher.GopherIt;
  268.         Success(fi);
  269.         
  270.         CASE gopherCommand OF
  271.         
  272.             cNewGopherFolder: BEGIN
  273.                 IF NOT gPoppingMenu THEN BEGIN
  274.                     gLastParentList:= TGopherList(NewList);
  275.                     FailNIL(gLastParentList);
  276.                     FOR i:= 1 TO fParentList.GetSize DO
  277.                         gLastParentList.InsertLast( fParentList.At( i));
  278.                     END;
  279.                     
  280.                 IF (gSameWindow 
  281.                     | ((gNumWindows>0) & (fParentList.GetSize >= gNumWindows)) ) THEN BEGIN
  282.                     PushMenu( gGopherData, gGopherTitle, gCurrentGopher);
  283.                     END
  284.                 ELSE BEGIN
  285.                     gApplication.OpenNew( cNewGopherFolder);        
  286.                     END;
  287.                     
  288.                 aGopher.fInfo:= DisposeIfHandle( aGopher.fInfo);
  289.                 gGopherData:= NIL;
  290.                 gLastParentList:= NIL;
  291.                 END;
  292.             
  293.             cNewGopherText: BEGIN
  294.                 gNewTextName:= aGopher.ShortName;
  295.                 gApplication.OpenNew( cNewGopherText);
  296.                 aGopher.fInfo:= DisposeIfHandle( aGopher.fInfo);
  297.                 gGopherData:= NIL;
  298.                 END;
  299.  
  300.             cOpenGopherText: BEGIN            
  301.                 afList:= AppFileToList( gGopherFile);
  302.                 gApplication.OpenOld( cOpenGopherText, afList);
  303.                 aGopher.fInfo:= DisposeIfHandle( aGopher.fInfo);
  304.                 TObject(afList):= FreeListIfObject(afList);
  305.                 gGopherData:= NIL;
  306.                 END;
  307.                 
  308.             END;
  309.         
  310.         UpdateStatus;
  311.         END;
  312. END;
  313.  
  314. PROCEDURE TGopherDocument.Free; OVERRIDE;
  315. BEGIN
  316.     FreeData; 
  317.     TSortedList(fGopherList):= FreeListIfObject( fGopherList);
  318.     TSortedList(fParentList):= FreeListIfObject( fParentList);
  319.     INHERITED Free;
  320. END;
  321.  
  322. PROCEDURE TGopherDocument.FreeData; OVERRIDE;
  323. { this is called from Doc.Revert & other such methods that re-read data }
  324. BEGIN
  325.     if (fLongTitle<>NIL) THEN Handle(fLongTitle):= DisposeIfHandle(Handle(fLongTitle)); 
  326.     IF (fGopherList<>NIL) THEN fGopherList.FreeAll;  {empty but valid for new data }
  327. END;
  328.  
  329.  
  330. PROCEDURE TGopherDocument.DoInitialState; OVERRIDE;
  331. { called for New and Revert... -- load in all 'IGo4' resources }
  332. VAR
  333.         hData, hr    : Handle;
  334.         i, err, rID, nlinks : integer;
  335.         str    : str255;
  336.         rType: ResType;
  337.         usePref: boolean;
  338. BEGIN
  339.     IF (fGopherList.GetSize = 0) THEN BEGIN
  340.                 { may have read in data during IGopherDocument...}
  341.         hData:= NewHandle(0);
  342.         nlinks:= Count1Resources(kGopherScrapType); {?? assume Pref rez is 1st }
  343.         usePref:= (nlinks>0);
  344.         IF NOT usePref THEN nlinks:= CountResources(kGopherScrapType);
  345.         FOR i:= 1 TO nlinks DO BEGIN
  346.             IF usePref THEN hr:= Get1IndResource(kGopherScrapType, i)
  347.             ELSE hr:= GetIndResource(kGopherScrapType, i);
  348.             GetResInfo( hr, rID, rType, str);
  349.             IF (rID > 127) THEN BEGIN {skip sys rez, bundle id rez}
  350.                 {??! check that hr[end]<>0, and drop 0 if need be !??}
  351.                 HLock( hr);
  352.                 err:= HandAndHand( hr, hData);
  353.                 HUnlock( hr);
  354.                 ReleaseResource( hr);
  355.                 END;
  356.             END;
  357.         str[0]:= chr(4);            {append dot-cr-lf-NULL end of data}
  358.         str[1]:= '.'; str[2]:= chr(13); str[3]:= chr(10); str[4]:= chr(0);
  359.         err:= PtrAndHand( @str[1], hData, 4); 
  360.         IF (nLinks>0) THEN fGopherList.ReadLinks( hData);
  361.         DisposHandle( hData);
  362.         END;
  363.     {- SetMenuName('Untitled');}
  364. END;
  365.  
  366.  
  367. PROCEDURE TGopherDocument.UntitledName(VAR noName: Str255); OVERRIDE;
  368. VAR
  369.     gotParent: boolean;
  370.     aGopher: TGopher;
  371. BEGIN
  372.     noName:= kGopherNoname; 
  373.     gotParent:= (fParentList<>NIL) & (fParentList.GetSize>0);
  374.     IF gotParent THEN BEGIN
  375.         aGopher:= TGopher(fParentList.First);
  376.         noName:= aGopher.ShortName;
  377.         END;
  378.     IF (noName = kGopherNoname) THEN BEGIN
  379.         INHERITED UntitledName( noName);
  380.         IF gotParent THEN SetMenuName( noName);
  381.         END;
  382. END;
  383.  
  384. PROCEDURE TGopherDocument.SetMenuName( newName: str255);
  385. VAR
  386.     gotParent: boolean;
  387.     aGopher    : TGopher;
  388.     item        : integer;
  389. BEGIN    
  390.     gotParent:= (fParentList<>NIL) & (fParentList.GetSize>0);
  391.     IF gotParent THEN BEGIN
  392.         aGopher:= TGopher(fParentList.First);
  393.         IF (aGopher.ShortName = kGopherNoname) THEN BEGIN
  394.             SetString( aGopher.fTitle, newName);
  395.             IF (fParentPopup<>NIL) THEN BEGIN
  396.                 item:= CountMItems( fParentPopup.GetMenuHandle);
  397.                 SetItem( fParentPopup.GetMenuHandle, item, aGopher.ShortName);
  398.                 END;
  399.             END;
  400.         END;
  401. END;
  402.  
  403.  
  404. PROCEDURE TGopherDocument.DoMakeViews(forPrinting: BOOLEAN); OVERRIDE;
  405. { this comes after DoRead or DoInitialState...}
  406. VAR
  407.         aGopherWindow    : TGopherWindow;
  408.         aHandler    : TStdPrintHandler;
  409.         
  410.       Procedure InsertMenuName( aPar: TGopher);
  411.         BEGIN
  412.             AppendMenu( fParentPopup.GetMenuHandle, aPar.ShortName);
  413.         END;
  414. BEGIN
  415.     aGopherWindow := TGopherWindow( gViewServer.NewTemplateWindow(kGopherWindID, SELF));
  416.     FailNIL(aGopherWindow);                      
  417.     aGopherWindow.IGopherWindow;
  418.     
  419.     fGopherView := TGopherView(aGopherWindow.FindSubView('GoVw')); 
  420.     FailNIL( fGopherView);
  421.     fStatus    := TStaticText(aGopherWindow.FindSubView('STAT'));
  422.     fGopherList.SetStatus(fStatus);
  423.     fDropBut    := TIcon(aGopherWindow.FindSubView('DROP'));
  424.     fParentPopup := TPopup(aGopherWindow.FindSubView('pPar')); 
  425.     FailNIL( fParentPopup);
  426.     { remove it from view til needed... == HideParentMenu ?}
  427.     fParentPopup.Show( FALSE, NOT kRedraw);
  428.     fParentPopup.ViewEnable( FALSE, NOT kRedraw);
  429.     DelMenuItem( fParentPopup.GetMenuHandle, 1); { drop test value }
  430.     IF fParentList<>NIL THEN BEGIN
  431.         fParentList.Each(insertMenuName);
  432.         fParentList.SetStatus(fStatus);
  433.         END;
  434.     
  435.     New(aHandler);
  436.     FailNIL(aHandler);
  437.     aHandler.IStdPrintHandler(SELF,                     { its document }
  438.                               fGopherView,                    { its view }
  439.                               NOT kSquareDots,            { does not have square dots }
  440.                               kFixedSize,                 { horzontal page size is fixed }
  441.                               NOT kFixedSize);            { vertical page size is variable }
  442.     ShowReverted;
  443. END;
  444.  
  445.  
  446. PROCEDURE TGopherDocument.UpdateStatus;
  447. VAR  aStr: Str255;
  448. BEGIN
  449.     IF (fStatus<>NIL) THEN BEGIN
  450.         IF fStatus.Focus THEN ;
  451.         IF (fLongTitle<>NIL) THEN fStatus.SetText( fLongTitle^^, kRedraw)
  452.         ELSE BEGIN
  453.             GetTitle( aStr);
  454.             IF (length(aStr)>0) THEN fStatus.SetText(aStr, kRedraw)
  455.             ELSE fStatus.SetText('', kRedraw);
  456.             END;
  457.         END;
  458. END;
  459.  
  460.  
  461. PROCEDURE TGopherDocument.ShowReverted; OVERRIDE;
  462. VAR
  463.     shorty: str255;
  464. BEGIN
  465.     fGopherView.IGopherView( fGopherList); 
  466.     
  467.     IF (fLongTitle<>NIL) THEN BEGIN
  468.         IF (fStatus<>NIL) THEN fStatus.SetText( fLongTitle^^, NOT kRedraw);
  469.         shorty:= fLongTitle^^;
  470.         if length(shorty) > 32 then begin shorty[0]:= chr(32); shorty[32]:= '…'; end;
  471.         {-----  is this bombing us !!!
  472.         IF (fTitle = NIL) THEN fTitle:= NewString( shorty)
  473.         ELSE BEGIN
  474.             SetString( fTitle, shorty);
  475.             FailMemError;
  476.             END;
  477.         --------}
  478.         END;
  479.         
  480.     INHERITED ShowReverted;
  481. END;
  482.  
  483.     
  484. PROCEDURE TGopherDocument.DoRead( aFile:TFile; forPrinting: BOOLEAN); OVERRIDE;
  485. VAR
  486.         numChars: longint;
  487.         hData    : Handle;
  488.         err        : OSErr;        
  489.         p            : CharsPtr;
  490.         aStr    : Str255;
  491. BEGIN    
  492.     if (fGopherList<>NIL) THEN fGopherList.FreeAll;  {? do we need this here? == SELF.FreeData, called from Revert method }
  493.     FailOSErr( aFile.GetDataLength( numChars));
  494.     
  495.     hData:= NewHandle( numChars+1);    
  496.     FailNIL( hData);
  497.     HLock( hData);
  498.     err:= aFile.ReadData( hData^, numChars);
  499.     longint(p):= longint(hData^) + numChars; 
  500.     p^[0]:= chr(0); { NULL terminator...}
  501.     HUnlock(hData);
  502.     IF (err=0) THEN fGopherList.ReadLinks( hData);
  503.     DisposHandle( hData);
  504.     FailOSErr( err);
  505.     
  506.     GetTitle( aStr); 
  507.     IF (length(aStr)>0) THEN SetMenuName(aStr);
  508.     
  509.     {!? read window location/size from rez fork...}
  510. END;
  511.  
  512.  
  513. PROCEDURE TGopherDocument.DoNeedDiskSpace(itsFile: TFile;
  514.                                                             VAR dataForkBytes, rsrcForkBytes: LONGINT); OVERRIDE;
  515. VAR h : handle;
  516. BEGIN
  517.     {---
  518.     h:= fTextData.fChars;
  519.     dataForkBytes := dataForkBytes + GetHandleSize(h);
  520.     -----}
  521.     INHERITED DoNeedDiskSpace(itsFile, dataForkBytes, rsrcForkBytes);
  522. END;
  523.  
  524.  
  525. PROCEDURE TGopherDocument.DoWrite( aFile:TFile; makingCopy: BOOLEAN); OVERRIDE;
  526. VAR
  527.     h : Handle;
  528.     numChars: longint;
  529. BEGIN
  530.     {- INHERITED DoWrite( aRefNum, makingCopy); } {write out print info }
  531.  
  532.         { Write out the text }
  533.     IF optionKeyIsDown THEN { damn magic key to write server-style links }
  534.         h:= fGopherList.WriteLinksForServer
  535.     ELSE
  536.         h:= fGopherList.WriteLinks;
  537.     numChars := GetHandleSize(h) - 1;{! drop NULL terminator }
  538.     HLock( h);
  539.     FailOSErr( aFile.WriteData( h^, numChars));
  540.     HUnlock( h);
  541.     DisposHandle( h);
  542.         {!? write window location/size to rez fork...}
  543. END;
  544.  
  545.  
  546. PROCEDURE TGopherDocument.DoEvent(eventNumber: EventNumber; 
  547.                                             source: TEventHandler; event: TEvent); OVERRIDE;
  548. BEGIN
  549.     IF (source=fParentPopup) THEN  
  550.             PopMenu(fParentPopup.GetCurrentItem)
  551.     ELSE
  552.             INHERITED DoEvent( eventNumber, source, event);
  553. END;
  554.  
  555.  
  556.  
  557. PROCEDURE  TGopherDocument.DoMenuCommand(aCommandNumber: CommandNumber); OVERRIDE;
  558. VAR
  559.         menu, item, nSel: integer;
  560.         aGopherEditCommand : TGopherEditCommand;
  561.         aGopherPasteCommand: TGopherPasteCommand;
  562.         aGopher: TGopher;
  563.         vbounds: VRect;
  564.         aRow, totalRows: integer;
  565.         oldKind: Char;
  566.         bGopher: TGopher;
  567.         arect    : Rect;
  568.         
  569.     PROCEDURE EditOldGopher;
  570.     BEGIN
  571.         gApplication.CommitLastCommand; 
  572.         aRow:= fGopherView.FirstSelectedCell.v;
  573.         aGopher:= fGopherView.GopherAt(aRow); 
  574.         IF (aGopher<>NIL) THEN BEGIN
  575.             oldKind:= aGopher.fType;
  576.             IF aGopher.Edit THEN BEGIN
  577.                 IF (aGopher.fType<>oldKind) &
  578.                  fGopherList.CopyToNewKind( aGopher.fType, aGopher, bGopher) THEN BEGIN
  579.                     aGopher.Free;
  580.                     {! must re-insert bgopher into list }
  581.                     fGopherList.AtPut( aRow, bGopher);
  582.                     END;
  583.                 SetChangeCount(GetChangeCount+1);
  584.                 fGopherView.RowToVRect( aRow, 1, vbounds); 
  585.                 fGopherView.InvalidateVRect( vbounds);
  586.                 END;
  587.             END;
  588.     END;
  589.         
  590.     PROCEDURE InsertNewGopher;
  591.     VAR  path: Handle;
  592.     BEGIN            
  593.         gApplication.CommitLastCommand; 
  594.         aRow:= fGopherView.LastSelectedCell.v;
  595.         IF aRow=0 THEN aRow:= fGopherList.GetSize;
  596.         totalRows:= fGopherList.GetSize + 1;
  597.         aRow:= aRow+1;
  598.         NEW(aGopher);
  599.         FailNIL( aGopher);
  600.         oldKind:= aGopher.fType;
  601.         path:= Str2Handle('/put/path/to/document/here');
  602.         aGopher.IGopher('Put.Host.Name.Here', path,
  603.                                         'Put Title of Gopher Link Here', 70, '0');
  604.         path:= DisposeIfHandle(path);
  605.         aGopher.fOwnerList:= fGopherList;
  606.         IF aGopher.Edit THEN BEGIN
  607.             IF (aGopher.fType<>oldKind) &
  608.              fGopherList.CopyToNewKind( aGopher.fType, aGopher, bGopher) THEN BEGIN
  609.                 aGopher.Free;
  610.                 aGopher:= bGopher;
  611.                 END;
  612.             fGopherList.InsertBefore( aRow, aGopher);
  613.             fGopherView.InsRowBefore( aRow, 1, fGopherView.fRowHeight);
  614.             fGopherView.RowToVRect( aRow, totalRows-aRow+1, vbounds); 
  615.             fGopherView.InvalidateVRect( vbounds);
  616.             fGopherView.UpdateSize;
  617.             SetChangeCount(GetChangeCount+1);
  618.             END
  619.         ELSE
  620.             aGopher.Free;
  621.         {select the pasted cells & scroll into view ?!!}
  622.     END; 
  623.     
  624.  
  625. BEGIN
  626.     CommandToMenuItem(aCommandNumber, menu, item);        
  627.     CASE aCommandNumber OF
  628.  
  629.         cSelectAll:  BEGIN
  630.                 SetRect( aRect, 1, 1, fGopherView.fNumOfCols, fGopherView.fNumOfRows);
  631.                 fGopherView.SetSelectionRect( aRect, kDontExtend, kHighlight, kSelect);
  632.                 END;
  633.                 
  634.         cCut, cCopy, cClear: BEGIN
  635.                 gApplication.CommitLastCommand; {paste relies on clipView data til commit}
  636.                 NEW(aGopherEditCommand);
  637.                 FailNIL(aGopherEditCommand);
  638.                 aGopherEditCommand.IGopherEditCommand(SELF, aCommandNumber);
  639.                 PostCommand( aGopherEditCommand);
  640.                 END;
  641.  
  642.         cPaste:
  643.                 IF gClipboardMgr.fClipView.ContainsClipType(kGopherScrapType) THEN BEGIN
  644.                     gApplication.CommitLastCommand; {copy/cut/.. relies on clipView data til commit}
  645.                     NEW(aGopherPasteCommand);
  646.                     FailNIL(aGopherPasteCommand);
  647.                     aGopherPasteCommand.IGopherPasteCommand(SELF);
  648.                     PostCommand( aGopherPasteCommand);
  649.                     END
  650.                 { ELSE IF gClipView.ContainsClipType('TEXT') THEN BEGIN
  651.                     // try to convert from TEXT to gopher data...
  652.                     END
  653.                 }
  654.                 ELSE  
  655.                     INHERITED DoMenuCommand(aCommandNumber);
  656.  
  657.         cNewGopherLink    : InsertNewGopher;
  658.         cEditGopher    : EditOldGopher;
  659.         
  660.         OTHERWISE
  661.             INHERITED DoMenuCommand(aCommandNumber);
  662.         END;
  663. END;
  664.  
  665.  
  666.  
  667.  
  668. PROCEDURE TGopherDocument.DoSetupMenus; OVERRIDE;
  669. VAR 
  670.     nsel    : integer;
  671.     indexSelection    : Boolean;
  672. BEGIN
  673.   INHERITED DoSetupMenus;    
  674.     
  675.     nsel:= 0;
  676.     IF (fGopherView<>NIL) & (fGopherView.FirstSelectedCell.v > 0) THEN 
  677.         nsel:= 1 + fGopherView.LastSelectedCell.v - fGopherView.FirstSelectedCell.v;
  678.     indexselection:= nsel>0;
  679.     
  680.     {IF indexSelection & clipHasSeqText... THEN CanPaste('TEXT'); }
  681.     gClipboardMgr.CanPaste(kGopherScrapType);
  682.     
  683.     Enable(cCut, indexSelection);
  684.     Enable(cCopy, indexSelection);
  685.     Enable(cClear, indexSelection);
  686.     Enable(cSelectAll, TRUE);
  687.      
  688.     Enable( cNewGopherLink, gAllowLinkEdits);
  689.     Enable( cEditGopher, gAllowLinkEdits & (nsel>=1)); 
  690.  
  691. END;
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703. { TGopherView -----------------------------}
  704.  
  705.  
  706. PROCEDURE TGopherView.IGopherView( aGopherList: TGopherList);
  707. VAR  vbounds: VRect;
  708. BEGIN
  709.     fGopherList:= aGopherList;
  710.     fLocked:= FALSE;
  711.     fRowheight:= GetRowHeight(1);
  712.     UpdateSize; 
  713.     UpdateAllWidths;
  714. END;
  715.  
  716.  
  717. PROCEDURE TGopherView.Free; OVERRIDE;
  718. BEGIN
  719.     INHERITED Free;
  720. END;
  721.  
  722.  
  723.  
  724. PROCEDURE TGopherView.UpdateSize;
  725. VAR      diff: integer;
  726. BEGIN
  727.     IF Focus THEN ;
  728.     
  729.     IF (fGopherList<>NIL) THEN BEGIN
  730.             
  731.         diff:= fGopherList.GetSize - fNumOfRows;
  732.         IF (diff>0) THEN InsRowLast( diff, fRowheight)     
  733.         ELSE IF (diff<0) THEN DelRowLast( -diff);
  734.         END
  735.     ELSE
  736.         DelRowLast( fNumOfRows);
  737. END;
  738.  
  739.  
  740. PROCEDURE TGopherView.UpdateWidth(aGopher: TGopher);
  741. VAR            maxpixels : integer;
  742. BEGIN
  743.     SetPortTextStyle(gItemStyle);  
  744.     maxpixels:= max(GetColWidth(2), StringWidth(aGopher.fTitle^^) + 5);
  745.     SetColWidth(2, 1, maxpixels);  
  746. END;
  747.  
  748. {
  749.     grid columns (1-2 perm, 3-6 optional)
  750.     1            2            3            4            5            6
  751.     icon    title    kind    path    host    port
  752. }
  753. PROCEDURE TGopherView.UpdateAllWidths;
  754. VAR            maxIcon, max2, max3, max4, max5, max6, maxSize, maxDate : integer;
  755.                 saveport : GrafPtr;
  756.                 
  757.         PROCEDURE findMaxLength(aGopher: TGopher);
  758.         BEGIN
  759.             max2:= max(max2, StringWidth(aGopher.fTitle^^) + 5);
  760.             IF (gShowDate & (aGopher.fDate<>NIL)) THEN 
  761.                 maxDate:= max(maxDate,6+StringWidth(aGopher.fDate^^));
  762.             IF (gShowSize & (aGopher.fDataSize<>NIL)) THEN 
  763.                 maxSize:= max(maxSize,6+StringWidth(aGopher.fDataSize^^));
  764.         END;
  765. BEGIN
  766.     GetPort( saveport);
  767.     SetPort( gWorkPort);
  768.     SetPortTextStyle( gItemStyle);  {<< for proper StringWidth }    
  769.  
  770.     case gIconSize of
  771.         1: maxIcon:= 16;  {12 + 4}
  772.         2: maxIcon:= 20;  {16 + 4}
  773.         3: maxIcon:= 36;
  774.         otherwise maxIcon:= 36;
  775.         END;
  776.  
  777.     max2:= GetColWidth(2);
  778.     maxDate:= 0;
  779.     maxSize:= 0;
  780.     IF fGopherList<>NIL THEN fGopherList.Each( findMaxLength );
  781.     IF (gShowKind) THEN max3:= StringWidth('Binhex encoded file') ELSE max3:= 0;
  782.     IF (gShowPath) THEN max4:= StringWidth('1/this/is/a/long/path') ELSE max4:= 0;
  783.     IF (gShowHost) THEN max5:= StringWidth('some.where.indiana.edu') ELSE max5:= 0;
  784.     IF (gShowPort) THEN max6:= StringWidth('12345') ELSE max6:= 0;
  785.     SetPort( saveport);
  786.  
  787.     IF Focus THEN ;
  788.     fRowheight:= maxIcon;
  789.     SetRowHeight( 1, fNumOfRows, fRowheight);  
  790.     SetColWidth( 1, 1, maxIcon);  
  791.     SetColWidth( 2, 1, max2); 
  792.     SetColWidth( 3, 1, maxDate);
  793.     SetColWidth( 4, 1, maxSize);
  794.     SetColWidth( 5, 1, max3);
  795.     SetColWidth( 6, 1, max4);
  796.     SetColWidth( 7, 1, max5);
  797.     SetColWidth( 8, 1, max6);
  798. END;
  799.  
  800.  
  801. PROCEDURE TGopherView.addToGopherList(aGopher: TGopher);
  802. VAR  aRect: VRect;
  803. BEGIN
  804.     fGopherList.InsertLast( aGopher);
  805.     InsRowLast( 1, fRowheight);    
  806.     UpdateWidth( aGopher);    
  807.     RowToVRect( fNumOfRows, 1, aRect);
  808.     InvalidateVRect( aRect);  
  809. END;
  810.  
  811. FUNCTION TGopherView.GopherAt( aRow: integer): TGopher;  
  812. BEGIN
  813.     IF (fGopherList=NIL) | (aRow>fGopherList.GetSize) THEN GopherAt:= NIL
  814.     ELSE GopherAt:= TGopher(fGopherList.At( aRow));  
  815. END;
  816.  
  817.  
  818. PROCEDURE TGopherView.EachSelectedRowDo( PROCEDURE DoToRow( aRow: Integer)); 
  819. VAR
  820.         aCell: GridCell;
  821.         irow, jcol, mincol, maxcol: integer;
  822. BEGIN
  823.     mincol:=    FirstSelectedCell.h;
  824.     maxcol:=  LastSelectedCell.h;
  825.     FOR irow:= FirstSelectedCell.v TO LastSelectedCell.v DO BEGIN
  826.         aCell.v:= irow;
  827.         for jcol:= mincol to maxcol DO BEGIN
  828.             aCell.h:= jcol;
  829.             IF isCellSelected( aCell) THEN BEGIN
  830.                 DoToRow( irow);
  831.                 Leave; { jcol...}
  832.                 END;
  833.             END;
  834.         END;
  835. END;
  836.  
  837.  
  838. PROCEDURE TGopherView.DrawCell(aCell: GridCell; aRect: VRect); OVERRIDE;
  839. VAR     aGopher    : TGopher;
  840.             qdRect: Rect;
  841. BEGIN
  842.     aGopher:= GopherAt(aCell.v);
  843.     IF (aGopher<>NIL) then BEGIN
  844.         ViewToQDRect( aRect, qdRect);
  845.         IF Focus THEN ;
  846.         GetClip( gSaveclip);
  847.         ClipFurtherTo( qdRect, gZeroPt);
  848.         MoveTo( aRect.left, aRect.bottom-4); 
  849.         SetPortTextStyle(gItemStyle); { this was failing in DrawContents ??!}
  850.         CASE aCell.h OF
  851.             1    : aGopher.DrawIcon( qdRect, gIconSize);
  852.             2    : aGopher.DrawTitle(qdRect);
  853.             3    : IF (gShowDate) THEN aGopher.DrawDate( qdRect);
  854.             4    : IF (gShowSize) THEN aGopher.DrawSize( qdRect);
  855.             5    : IF (gShowKind) THEN aGopher.DrawKind( qdRect);
  856.             6    : IF (gShowPath) THEN aGopher.DrawPath( qdRect);
  857.             7    : IF (gShowHost) THEN aGopher.DrawHost( qdRect);
  858.             8    : IF (gShowPort) THEN aGopher.DrawPort( qdRect);
  859.             END;
  860.         SetClip( gSaveclip);
  861.         END;
  862. END;
  863.  
  864. PROCEDURE TGopherView.DrawRangeOfCells(startCell, stopCell: GridCell; aRect: VRect); 
  865.                                         OVERRIDE; {from TGridView method}
  866. BEGIN
  867.     INHERITED DrawRangeOfCells( startCell, stopCell, aRect);
  868. END;
  869.  
  870. PROCEDURE TGopherView.DrawContents; OVERRIDE;
  871. BEGIN
  872.     SetPortTextStyle(gItemStyle); {< this one is failing in Mapp3 }
  873.     {- IF gConfiguration.hasColorQD then RGBForeColor( gItemColor);     }
  874.     INHERITED DrawContents;
  875. END;
  876.  
  877.  
  878. PROCEDURE  TGopherView.DoMouseCommand(VAR theMouse: VPoint; event: TToolboxEvent;
  879.                                                hysteresis: Point); OVERRIDE;
  880. VAR
  881.     aRow: integer;
  882.     aCell    : GridCell;
  883.     aDoubleClick: boolean;
  884.     vpt        : VPoint;
  885.     gridPart: GridViewPart;    
  886.     aListSlider    : TListSlider;
  887.     
  888.     PROCEDURE DoMouseCommandByRow(VAR theMouse: VPoint; event: TToolboxEvent;
  889.                                                hysteresis: Point);
  890.     { from TGridView.DoMouseCommand, w/ TCellSelectCommand replaced by TRowSelect...}
  891.     VAR
  892.         aCell    : GridCell;
  893.         aRowSelectCommand: TRowSelectCommand;
  894.     BEGIN
  895.         IF IdentifyPoint(theMouse, aCell) <> badChoice THEN BEGIN
  896.             New(aRowSelectCommand);
  897.             FailNIL(aRowSelectCommand);
  898.             aRowSelectCommand.IRowSelectCommand(SELF, theMouse, event.IsShiftKeyPressed, 
  899.                                 event.IsCommandKeyPressed);
  900.             PostCommand( aRowSelectCommand);
  901.             END;
  902.     END;
  903.  
  904. BEGIN
  905.     aDoubleClick:= event.fClickCount > 1;
  906.     gridPart:= IdentifyPoint(theMouse, aCell);
  907.     aRow:= aCell.v;
  908.     
  909.     IF aDoubleClick THEN BEGIN
  910.       TGopherDocument(fDocument).DoGopher( GopherAt(aRow));
  911.         END
  912.         
  913.     ELSE IF (event.IsShiftKeyPressed |event.IsCommandKeyPressed 
  914.                 | event.IsOptionKeyPressed) THEN BEGIN 
  915.         DoMouseCommandByRow(theMouse,event,hysteresis);
  916.         END
  917.         
  918.     ELSE IF gridPart <> badChoice THEN BEGIN
  919.         aCell    := VPointToLastCell(TheMouse);
  920.         IF isCellSelected(aCell) THEN BEGIN
  921.             New(aListSlider);
  922.             FailNIL(aListSlider);
  923.             aListSlider.IListSlider(SELF, fGopherList, v,aRow);
  924.             PostCommand( aListSlider);
  925.             END
  926.         ELSE BEGIN
  927.             SetEmptySelection(kHighlight);
  928.             event.fEventRecord.modifiers := bOr(event.fEventRecord.modifiers,shiftKey);
  929.           DoMouseCommandByRow(theMouse,event,hysteresis);
  930.             END;
  931.         END;
  932. END;
  933.  
  934.  
  935.  
  936. FUNCTION  TGopherView.HandleMouseDown( theMouse: VPoint; event: TToolboxEvent; 
  937.                              hysteresis: Point):BOOLEAN; OVERRIDE;
  938. BEGIN        
  939.     HandleMouseDown:= INHERITED HandleMouseDown(theMouse,event,hysteresis);
  940. END;
  941.  
  942.  
  943. FUNCTION TGopherView.ContainsClipType(aType: ResType): BOOLEAN; OVERRIDE;
  944. BEGIN
  945.     ContainsClipType := aType = kGopherScrapType;
  946.     {!? also (aType = 'TEXT') may be gopher data}
  947. END;
  948.  
  949. PROCEDURE TGopherView.WriteToDeskScrap; OVERRIDE;
  950. VAR
  951.         textScrap    : Handle;
  952.         err                : OSErr;
  953.         format        : integer;
  954. BEGIN
  955.     textScrap:= fGopherList.WriteLinks;
  956.                                 {^^ do this just for gopherList items selected in this view ?? }
  957.     SetHandleSize( textScrap, GetHandleSize(textScrap)-1); {! drop NULL terminator }
  958.     err := gClipboardMgr.PutDeskScrapData('TEXT', textScrap); {? instead/also put as kGopherScrapType}
  959.     textScrap := DisposeIfHandle(textScrap);
  960.     FailOSErr(err);
  961. END;
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972. { TGopherWindow ------------------------}
  973.  
  974.  
  975. PROCEDURE TGopherWindow.IGopherWindow;
  976. BEGIN    
  977.     IPrefWindow;
  978.     fWantSave:= FALSE; {TRUE !?}
  979. END;
  980.  
  981. PROCEDURE TGopherWindow.DoEvent(eventNumber: EventNumber; 
  982.                                             source: TEventHandler; event: TEvent); OVERRIDE; 
  983. BEGIN
  984.     INHERITED DoEvent( eventNumber, source, event);
  985.     {--------
  986.     CASE eventNumber OF
  987.         mSendit            : BEGIN Sendit; Close; END;
  988.         Otherwise 
  989.                 INHERITED DoEvent( eventNumber, source, event);
  990.         END;
  991.     ---------}
  992. END;
  993.     
  994.  
  995. FUNCTION  TGopherWindow.HandleMouseDown( theMouse: VPoint; event: TToolboxEvent; 
  996.                              hysteresis: Point):BOOLEAN; OVERRIDE;
  997. VAR
  998.         aDlog: TDialogView; 
  999.         aCell    : GridCell;
  1000.         aWMgrWindow:        WindowPtr;
  1001.         whereMouseDown:     integer;
  1002.         aPartCode: integer;
  1003.         
  1004.         { a mess, but it works... we could avoid this by subclassing the
  1005.             fStatus & fDropBut items to pass on HandleMouseDown to the hidden Popup
  1006.             -- cleaner but more work.
  1007.             ^^^ Move this to Dialog.HandleMouseDown --
  1008.                 -- Here we get menu popups from behind windows...
  1009.         }
  1010.     FUNCTION TestStatPopup: BOOLEAN;
  1011.     VAR     subViewPt: VPoint;  dropMenu: Boolean;
  1012.     BEGIN
  1013.         IF TGopherDocument(fDocument).fStatus = NIL THEN 
  1014.             TestStatPopup := FALSE
  1015.         ELSE BEGIN
  1016.             subViewPt := theMouse;
  1017.             TGopherDocument(fDocument).fStatus.SuperToLocal(subViewPt);
  1018.             DropMenu:= TGopherDocument(fDocument).fStatus.ContainsMouse(subViewPt);
  1019.             IF NOT DropMenu THEN BEGIN
  1020.                 subViewPt := theMouse;
  1021.                 TGopherDocument(fDocument).fDropBut.SuperToLocal(subViewPt);
  1022.                 DropMenu:= TGopherDocument(fDocument).fDropBut.ContainsMouse(subViewPt);
  1023.                 END;
  1024.             IF DropMenu THEN BEGIN
  1025.                 TGopherDocument(fDocument).ShowParentMenu;
  1026.                 TestStatPopup:= 
  1027.                 TGopherDocument(fDocument).fParentPopup.HandleMouseDown(theMouse,event,hysteresis);
  1028.                 TGopherDocument(fDocument).HideParentMenu;
  1029.                 END
  1030.             ELSE
  1031.                 TestStatPopup := FALSE;
  1032.         END;
  1033.     END;
  1034.         
  1035. BEGIN        
  1036.     IF (gApplication.GetActiveWindow = SELF) THEN BEGIN
  1037.         CASE SELF.GetPartCode(theMouse) OF
  1038.             inContent: 
  1039.                 IF gApplication.GetActiveWindow <> SELF THEN 
  1040.                     Select 
  1041.                 ELSE IF NOT TestStatPopup THEN
  1042.                     HandleMouseDown:= INHERITED HandleMouseDown(theMouse,event,hysteresis);
  1043.             
  1044.             {-----------
  1045.             inDrag:
  1046.                 IF theCommandKey THEN BEGIN  
  1047.                     TGopherDocument(fDocument).ShowParentMenu;
  1048.                     HandleMouseDown:= 
  1049.                     TGopherDocument(fDocument).fParentPopup.HandleMouseDown(theMouse,event,hysteresis);
  1050.                     TGopherDocument(fDocument).HideParentMenu;
  1051.                     END
  1052.                 ELSE  
  1053.                     MoveByUser(where);
  1054.             -----------}
  1055.         
  1056.             Otherwise 
  1057.                 HandleMouseDown:= INHERITED HandleMouseDown(theMouse,event,hysteresis);
  1058.             END
  1059.         END
  1060.     ELSE
  1061.         HandleMouseDown:= INHERITED HandleMouseDown(theMouse,event,hysteresis);
  1062. END;
  1063.  
  1064.  
  1065.  
  1066. PROCEDURE TGopherWindow.SetPrefID;  
  1067. BEGIN
  1068.     gPrefWindID:= kGopherWindID; gPrefWindName:= 'TGopherWindow';
  1069. END;
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079. {    TGopherPrefs -------------------------- }
  1080.             
  1081. PROCEDURE TGopherPrefs.Initialize; OVERRIDE;
  1082. BEGIN
  1083.     inherited Initialize;
  1084.     fInitted:= false;
  1085. END;
  1086.  
  1087. PROCEDURE TGopherPrefs.IGopherPrefs;
  1088. VAR        ascroller: TScroller;
  1089. BEGIN    
  1090.     IPrefWindow;
  1091.     fWantSave:= TRUE;
  1092.  
  1093.     fFont         := TPopup(FindSubView('FONT'));  
  1094.   fFSize       := TPopup(FindSubView('pSIZ'));  
  1095.   fFSizeNum    := TNumberText(FindSubView('nSIZ'));  
  1096.   fSmall        := TRadio(FindSubView('rSML'));
  1097.   fMid            := TRadio(FindSubView('rMID'));
  1098.   fBig            := TRadio(FindSubView('rBIG'));
  1099.   fPath            := TCheckBox(FindSubView('path'));
  1100.   fHost            := TCheckBox(FindSubView('host'));
  1101.   fPort            := TCheckBox(FindSubView('port'));
  1102.   fKind            := TCheckBox(FindSubView('kind'));    
  1103.   fDate            := TCheckBox(FindSubView('date'));    
  1104.   fDataSize    := TCheckBox(FindSubView('size'));    
  1105.  
  1106.   fUnknowns    := TCheckBox(FindSubView('unkn'));    
  1107.   fAllowLinkEdits    := TCheckBox(FindSubView('edtl'));    
  1108.     fUseServerMap   := TCheckBox(FindSubView('umap'));
  1109.     fEditServerMap    := TButton(FindSubView('emap'));
  1110.     fEditGopherMap    := TButton(FindSubView('gmap'));
  1111.     
  1112.         {diggings}
  1113.     fDigFolder    := TStaticText(FindSubView('tdig'));
  1114.     fDigVol            := TNumberText(FindSubView('vdig'));
  1115.     fDigDirID        := TNumberText(FindSubView('ddig'));
  1116.     fFindDig        := TButton(FindSubView('bdig'));
  1117.     fUseDig            := TCheckBox(FindSubView('digs'));
  1118.     IF fDigDirID.GetValue = 0 THEN BEGIN
  1119.         fUseDig.DimState( TRUE, kDontRedraw);
  1120.         fUseDig.ViewEnable(FALSE, kDontRedraw);
  1121.         END;
  1122.     
  1123.     fTFont             := TPopup(FindSubView('TFNT'));  
  1124.   fTFSize       := TPopup(FindSubView('pTSZ'));  
  1125.   fTFSizeNum    := TNumberText(FindSubView('nTSZ'));  
  1126.  
  1127.   fPTimeout   := TPopup(FindSubView('pTIM'));  
  1128.   fNTimeout        := TNumberText(FindSubView('nTIM'));  
  1129.  
  1130.   fSaveDefLinks   := TButton(FindSubView('bSDL'));  
  1131.   fRestoreDefLinks := TButton(FindSubView('bRDL'));  
  1132.  
  1133.     {-----
  1134.   fWindRadio:= TRadio(FindSubView('rWND'));
  1135.   fWindClust:= TCluster(FindSubView('cWND'));
  1136.   fWindNum    := TNumberText(FindSubView('nWND'));
  1137.     ----}
  1138.  
  1139.     ascroller:= fFont.GetScroller(FALSE);
  1140.     IF (ascroller<>NIL) THEN ascroller.fScrollLimit.v:= 256; {fix so prefview scroll bar shows}
  1141.     
  1142.     IF (false) {gWantFonts} THEN BEGIN {<< need menu for save of font pref }
  1143.                 {!!!! can't use AddResMenu for View TPopUp (bug in MacApp) }
  1144.         {?? fFont.SetPopup( MAGetMenu(mFont), 1 , kDontRedraw);}
  1145.         {?? fTFont.SetPopup( MAGetMenu(mFont), 1 , kDontRedraw);}
  1146.         {- AddResMenu(    fFont.GetMenuHandle, 'FONT');   }
  1147.         {- fFont.AdjustBotRight;}
  1148.         {- AddResMenu(    fTFont.GetMenuHandle, 'FONT'); }   
  1149.         {- fTFont.AdjustBotRight;}
  1150.         END;
  1151.     fInitted:= true;
  1152. END;
  1153.  
  1154.  
  1155. PROCEDURE TGopherPrefs.UpdateGopherDocs;
  1156.     PROCEDURE checkOpenDocs( aDoc: TDocument);
  1157.     BEGIN
  1158.         IF Member(TObject(aDoc), TGopherDocument) 
  1159.          | Member(TObject(aDoc), TTextDocument) THEN  
  1160.             aDoc.ShowReverted;
  1161.     END;
  1162. BEGIN
  1163.     gApplication.ForAllDocumentsDo(checkOpenDocs); 
  1164. END;
  1165.  
  1166.  
  1167. (***    
  1168.  
  1169.  
  1170.             DAMN THIS BUG HAS BITTEN ME A FEW TIMES...
  1171.             MACAPP THREE REQUIRES THAT ANY MENU CREATED WITH RESEDIT HAVE THE
  1172.             MENU ID SET TO EQUAL THE RESOURCE ID, IN THE MENU EDIT 
  1173.                 "EDIT MENU & MDEF ID..." 
  1174.             ITEM.
  1175.  
  1176. *****)
  1177.  
  1178.  
  1179. PROCEDURE TGopherPrefs.SetGlobals;
  1180. VAR  aStr: str255;
  1181.  
  1182.     PROCEDURE DoFontChange( VAR aStyle: TextStyle; aFontMenu: TPopup; aFontSize: TNumberText);
  1183.     VAR  aName: str255;   
  1184.     BEGIN
  1185.         aFontMenu.GetItemText( aFontMenu.GetCurrentItem, aName); 
  1186.         aStyle.tsFont:= GetFontNum( aName);
  1187.         aStyle.tsSize:= aFontSize.GetValue;
  1188.     END;
  1189.     
  1190.     PROCEDURE InitFonts( aStyle: TextStyle; aFontMenu: TPopup; aFontSize: TNumberText);
  1191.     VAR  aName: str255;  aFont, i, nitems: integer;   
  1192.     BEGIN
  1193.         nitems:= CountMitems(aFontMenu.GetMenuhandle);  
  1194.       for i:= 1 to nitems do begin
  1195.             aFontMenu.GetItemText( i, aName); 
  1196.             GetFNum( aName, aFont);
  1197.             if (aFont = aStyle.tsFont) then begin                
  1198.                 aFontMenu.SetCurrentItem( i, kDontRedraw);
  1199.                 LEAVE;
  1200.                 END;
  1201.             END;
  1202.         aFontSize.SetValue(aStyle.tsSize, kDontRedraw);
  1203.     END;
  1204.  
  1205.     
  1206. BEGIN    
  1207.      if (NOT fInitted) THEN EXIT(SetGlobals); { map3 -- prevent this call before IGopherPrefs}
  1208.     
  1209.     if fBig.IsOn then gIconSize:= 3
  1210.     else if fMid.IsOn then gIconSize:= 2
  1211.     else gIconSize:= 1;
  1212.      
  1213.     gShowDate:= fDate.IsOn;
  1214.     gShowSize:= fDataSize.IsOn;
  1215.  
  1216.     gListUnknowns:= fUnknowns.IsOn;
  1217.     gAllowLinkEdits:= fAllowLinkEdits.IsOn;
  1218.     gUseServerMap:= fUseServerMap.IsOn;
  1219.  
  1220.     gUseDig:= fUseDig.IsOn;
  1221.     fDigFolder.GetText( aStr); 
  1222.     gDigFolder:= aStr;
  1223.     gDigVol:= fDigVol.GetValue; 
  1224.     gDigDirID:= fDigDirID.GetValue;
  1225.      
  1226.     gShowKind:= fKind.IsOn;
  1227.     gShowPath:= fPath.IsOn;
  1228.     gShowHost:= fHost.IsOn;
  1229.     gShowPort:= fPort.IsOn;
  1230.     
  1231.     gTCPTimeout:= fNTimeout.GetValue;
  1232.     {----
  1233.     gSameWindow:= NOT fWindRadio.IsOn;
  1234.     gNumWindows:= fWindNum.GetValue;
  1235.     ----}
  1236.     
  1237.     IF gWantFonts THEN BEGIN
  1238.         DoFontChange( gItemStyle, fFont, fFSizeNum);
  1239.         DoFontChange( gDefaultSpecs.theTextStyle, fTFont, fTFSizeNum);
  1240.         END
  1241.     ELSE BEGIN
  1242.         InitFonts( gItemStyle, fFont, fFSizeNum);
  1243.         InitFonts( gDefaultSpecs.theTextStyle, fTFont, fTFSizeNum);
  1244.         END;    
  1245.  
  1246.     UpdateGopherDocs;    { if any gopherDocs/windows open -- update them !?}
  1247. END;
  1248.  
  1249.  
  1250. PROCEDURE TGopherPrefs.DoEvent(eventNumber: EventNumber; 
  1251.                                             source: TEventHandler; event: TEvent); OVERRIDE; 
  1252. VAR
  1253.         snum: Str255;
  1254.         val    : longint;
  1255.         changeit: boolean;
  1256.         index, i, len: integer;
  1257.         aGopherDoc: TGopherDocument;
  1258.         secondfront: WindowPtr;
  1259.  
  1260.     PROCEDURE DoEditMap( PROCEDURE ReadMap( h: Handle); mapId: integer; title: Str63);
  1261.     VAR        hText: Handle;
  1262.                 aWind    : TWindow;
  1263.                 aTextView: TDlogTextView;
  1264.                 dismisser : IDType;
  1265.                 aTitle: TStaticText;
  1266.     BEGIN
  1267.         hText:= TPrefApplication(gApplication).GetPreference('TEXT',mapId);
  1268.         IF (hText<>NIL) THEN BEGIN
  1269.             aWind := gViewServer.NewTemplateWindow(kServerEditDlog, NIL);
  1270.             FailNIL( aWind);          
  1271.             aTitle:= TStaticText( aWind.FindSubView('titl'));
  1272.             IF (aTitle<>NIL) THEN aTitle.SetText( title, kDontRedraw);
  1273.             aTextView:= TDlogTextView( aWind.FindSubView('TEXT'));
  1274.             FailNIL( aTextView);
  1275.             aTextView.IDlogTextView(hText);
  1276.  
  1277.             aWind.ShowReverted;  {! need to show hText ?!} 
  1278.             {- aWind.Open;  }
  1279.             
  1280.             aWind.SetModality( True); {!!! or PoseModally will fail !}
  1281.             dismisser := aWind.PoseModally;
  1282.             IF dismisser = 'OKAY' THEN BEGIN
  1283.                 hText:= aTextView.fHTE^^.hText;  
  1284.                 ReadMap( hText);
  1285.                 TPrefApplication(gApplication).SetPreference('TEXT', mapId, hText);
  1286.                 END;
  1287.                 
  1288.             aWind.CloseAndFree; {& free}
  1289.             gApplication.UpdateAllWindows;
  1290.             END;
  1291.     END;
  1292.     
  1293.     PROCEDURE FindDiggingFolder;
  1294.     VAR
  1295.          newreply    : StandardFileReply;
  1296.          oldreply    : SFReply;
  1297.          aStr            : Str63;
  1298.          okay            : boolean;
  1299.          pb                : CInfoPBRec;
  1300.          where        : point;
  1301.     BEGIN
  1302.         aStr:= ''; 
  1303.         okay:= FALSE;
  1304.         IF GestaltFlag( gestaltStandardFileAttr, gestaltStandardFile58) THEN BEGIN
  1305.             StandardPutFile( 'Locate diggings folder', 'Put diggings here', newreply);
  1306.             IF newreply.sfGood THEN with newreply do BEGIN
  1307.                 okay:= TRUE;
  1308.                 IF sfIsFolder THEN ; {??}
  1309.                 gDigVol:= sfFile.vRefNum;
  1310.                 gDigDirID:= sfFile.parID;
  1311.                 END;
  1312.             END
  1313.         ELSE BEGIN
  1314.             CenterSFPut( where);
  1315.             SFPutFile( where, 'Locate diggings folder', 'Put diggings here', NIL, oldreply);
  1316.             IF oldReply.good THEN BEGIN
  1317.                 okay:= TRUE;
  1318.                 gDigVol:= oldreply.vRefNum;
  1319.                 gDigDirID:= 0;
  1320.                 END;
  1321.             END;
  1322.         IF okay THEN BEGIN            
  1323.             WITH pb DO BEGIN
  1324.                 ioCompletion:= NIL;
  1325.                 ioNamePtr:= @aStr;
  1326.                 ioVRefNum:= gDigVol;
  1327.                 ioFDirIndex:= -1;
  1328.                 ioDirID:= gDigDirID;
  1329.                 END;
  1330.             IF noErr <> pbGetCatInfo( @pb, FALSE) THEN;
  1331.             gDigFolder:= aStr;
  1332.             fDigVol.SetValue( gDigVol, kDontRedraw);
  1333.             fDigDirID.SetValue( gDigDirID, kDontRedraw);
  1334.             fDigFolder.SetText( aStr, kRedraw);
  1335.             fUseDig.DimState( FALSE, kDontRedraw);
  1336.             fUseDig.ViewEnable(TRUE, kRedraw);
  1337.             END;
  1338.     END;
  1339.     
  1340.     PROCEDURE WritePrefLink( item: TGopher);
  1341.     VAR  hf: hcFile;
  1342.     BEGIN
  1343.         hcRewrite( hf);
  1344.         item.ToText( hf);
  1345.         hcClose( hf); {< puts 0 at end of h, we don't want that !}
  1346.         SetHandleSize( hf.h, GetHandleSize(hf.h)-1);
  1347.         index:= index+1;
  1348.         TPrefApplication(gApplication).SetPreference(kGopherScrapType, index, hf.h);
  1349.         hf.h:= DisposeIfHandle(hf.h);
  1350.     END;
  1351.     
  1352.     FUNCTION isFrontGopherDoc( aDoc: TDocument): Boolean;
  1353.     BEGIN
  1354.         isFrontGopherDoc:= FALSE;
  1355.         IF Member(TObject(aDoc), TGopherDocument) THEN BEGIN
  1356.             isFrontGopherDoc:= TWindow(aDoc.fWindowList.First).fWMgrWindow = secondfront;
  1357.             END;
  1358.     END;
  1359.  
  1360.  
  1361. BEGIN
  1362.     changeit:= false;
  1363.     CASE eventNumber OF
  1364.  
  1365.         mCheckboxHit,
  1366.         mEditTextHit,
  1367.         mListItemHit,
  1368.         mPictureHit,
  1369.         mIconHit,
  1370.         mRadioHit: BEGIN {come here with mRadioHit before window is open !!}
  1371.             {?? if (event<>NIL) then} changeit:= TRUE;
  1372.             END;
  1373.  
  1374.         mButtonHit : BEGIN
  1375.             if (event<>NIL) then changeit:= TRUE;        
  1376.             IF (source = fSaveDefLinks) THEN BEGIN
  1377.                 changeit:= FALSE;
  1378.                 secondfront:= WindowPtr( WindowPeek(FrontWindow)^.nextWindow);
  1379.                 TObject(aGopherDoc):= gApplication.fDocumentList.FirstThat(isFrontGopherDoc); 
  1380.                 IF (aGopherDoc<>NIL) THEN BEGIN
  1381.                     TPrefApplication(gApplication).DeleteAllPreference(kGopherScrapType);
  1382.                     index:= 1000;
  1383.                     aGopherDoc.fGopherList.Each( WritePrefLink);
  1384.                     END;
  1385.                 END            
  1386.             ELSE IF (source = fRestoreDefLinks) THEN BEGIN
  1387.                 changeit:= FALSE;        
  1388.                 TPrefApplication(gApplication).DeleteAllPreference(kGopherScrapType);
  1389.                 END 
  1390.             ELSE IF (source = fFindDig) THEN BEGIN
  1391.                 changeit:= FALSE;        
  1392.                 FindDiggingFolder;
  1393.                 END 
  1394.             ELSE IF (source = fEditGopherMap) THEN BEGIN
  1395.                 changeit:= FALSE;        
  1396.                 DoEditMap( ReadGopherMap,kGopherMapID,
  1397.                     'Gopher to Mac Type map (experimental)');
  1398.                 END 
  1399.             ELSE IF (source = fEditServerMap) THEN BEGIN
  1400.                 changeit:= FALSE;        
  1401.                 DoEditMap( ReadServerMap,kServerMapID,
  1402.                     'Server suffix to Mac Type map (experimental)');
  1403.                 END;
  1404.                 
  1405.             END;
  1406.                     
  1407.         mPopupHit: BEGIN
  1408.             if (event<>NIL) then changeit:= TRUE;
  1409.             IF (source = fFSize) THEN BEGIN
  1410.                 fFSize.GetItemText( fFSize.GetCurrentItem, snum);
  1411.                 {- MyPopupGetItemText( fFsize, fFsize.GetCurrentItem, snum);}
  1412.                 StringToNum( snum, val);
  1413.                 fFSizeNum.SetValue( val, kRedraw);
  1414.                 END
  1415.             ELSE IF (source = fTFSize) THEN BEGIN
  1416.                 fTFSize.GetItemText( fTFSize.GetCurrentItem, snum); 
  1417.                 {- MyPopupGetItemText( fTFSize, fTFSize.GetCurrentItem, snum);}
  1418.                 StringToNum( snum, val);
  1419.                 fTFSizeNum.SetValue( val, kRedraw);
  1420.                 END 
  1421.             ELSE IF (source = fPTimeout) THEN BEGIN
  1422.                 fPTimeout.GetItemText( fPTimeout.GetCurrentItem, snum); 
  1423.                 {- MyPopupGetItemText( fPTimeout, fPTimeout.GetCurrentItem, snum);}
  1424.                 StringToNum( snum, val);
  1425.                 fNTimeout.SetValue( val, kRedraw);
  1426.                 END;
  1427.             END;    
  1428.                 
  1429.         Otherwise BEGIN
  1430.             changeit:= FALSE;
  1431.             INHERITED DoEvent( eventNumber, source, event);
  1432.             END;
  1433.         END;
  1434.         
  1435.     IF changeit THEN SetGlobals;
  1436. END;
  1437.  
  1438.  
  1439. PROCEDURE TGopherPrefs.SetPrefID; OVERRIDE; 
  1440. BEGIN
  1441.     gPrefWindID:= kGopherPrefsID; gPrefWindName:= 'TGopherPrefs';
  1442. END;
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450. { OpenDialogs ....................................}
  1451.  
  1452. PROCEDURE InitializeGopher;
  1453. VAR        
  1454.         aWind: TGopherPrefs;
  1455.         havePrefs: boolean;
  1456.         saveMap: integer;
  1457.         
  1458.     procedure getSomeStyle( var aColor: RGBColor; var aTextStyle: TextStyle; rsrcID: integer);
  1459.     var  aTEView: TTEView;
  1460.     begin
  1461.         MAGetTextStyle(rsrcID, aTextStyle); {Mapp3}
  1462.         aColor:= aTextStyle.tsColor;
  1463.         {----
  1464.         aTEView := TTEView(gViewServer.DoCreateViews(NIL, NIL, rsrcID, gZeroVPt));
  1465.         FailNIL(aTEView);
  1466.         aColor:= aTEView.fTextStyle.tsColor;
  1467.       aTextStyle := aTEView.fTextStyle;
  1468.         aTEView.Free;
  1469.         ----}
  1470.     end;
  1471.  
  1472. BEGIN    
  1473.     gGopherHost    := 'gopher.micro.umn.edu'; {these 2 are not used, see 'IGo4' rez}
  1474.     gGopherPort := 70;
  1475.     gSaveclip:= NewRgn;
  1476.     gLastParentList:= NIL;
  1477.     gGopherDocSig    := kGopherFileType; {IGo4}
  1478.     gPoppingMenu:= FALSE;
  1479.  
  1480.     gIconSize:= 3;
  1481.     gShowDate:= FALSE;
  1482.     gShowSize:= FALSE;
  1483.     gShowKind:= FALSE;
  1484.     gShowPath:= FALSE;
  1485.     gShowHost:= FALSE;
  1486.     gShowPort:= FALSE;
  1487.     gSameWindow:= FALSE;
  1488.     gNumWindows:= 0;
  1489.     gListUnknowns:= FALSE;
  1490.     gUseServerMap:= FALSE;
  1491.     gAllowLinkEdits:= FALSE;
  1492.  
  1493.     gUseDig:= FALSE;
  1494.     gDigFolder:= '';
  1495.     gDigVol:=  gAppWDRef; {gAppVolRef;  }
  1496.     gDigDirID:= gAppDirID;
  1497.     
  1498.     getSomeStyle( gItemColor, gItemStyle, kGopherStyleID);
  1499.         {!! if this is 1st call (template from App rez not from Prefs),
  1500.             then need to set sane font/size depending on user installed fonts...
  1501.         }
  1502.     {- TPrefApplication(gApplication).OpenPreferenceFile;}
  1503.     IF TPrefApplication(gApplication).fPrefRefNum > 0 THEN BEGIN
  1504.         {- saveMap:= CurResFile; }
  1505.         UseResFile(TPrefApplication(gApplication).fPrefRefNum);
  1506.         gWantFonts:= Get1Resource( 'view', kGopherPrefsID) <> NIL;
  1507.         {- UseResFile(saveMap); }
  1508.         END
  1509.     ELSE
  1510.         gWantFonts:= FALSE;
  1511.         
  1512.     aWind := TGopherPrefs(gViewServer.NewTemplateWindow(kGopherPrefsID, NIL));
  1513.     IF (aWind<>NIL) THEN BEGIN
  1514.         aWind.IGopherPrefs;
  1515.         aWind.SetGlobals;
  1516.         IF NOT gWantFonts THEN aWind.SetPrefID; 
  1517.         aWind.Free;
  1518.         END;
  1519.     gWantFonts:= TRUE;
  1520.     
  1521.     IF gDeadStripSuppression THEN BEGIN
  1522.         IF Member(TObject(NIL), TGopherDocument) THEN;
  1523.         IF Member(TObject(NIL), TGopherWindow) THEN;
  1524.         IF Member(TObject(NIL), TGopherView) THEN;
  1525.         IF Member(TObject(NIL), TGopherPrefs) THEN;
  1526.         END;
  1527. END;
  1528.  
  1529.     
  1530. PROCEDURE OpenGopher;
  1531. VAR   isNowOpen, okay    : boolean;
  1532.             aRefNum    : integer;
  1533.             afList:    TList;
  1534.             
  1535.     PROCEDURE checkOpenDocs( aDoc: TDocument);
  1536.     BEGIN
  1537.         IF Member(TObject(aDoc), TGopherDocument) THEN BEGIN 
  1538.             TWindow(aDoc.fWindowList.First).Select; 
  1539.             isNowOpen:= TRUE;
  1540.             END;
  1541.     END;
  1542. BEGIN
  1543.     isNowOpen:= FALSE;
  1544.     afList:= NIL;
  1545.     {- gApplication.ForAllDocumentsDo(checkOpenDocs); }
  1546.     
  1547.     {! if frontwindow == gopherView/doc & an item is selected, then
  1548.         this command should do the equivalent of a doubleclick
  1549.         (see TGopherView.DoMouseCommand)
  1550.     --}
  1551.     
  1552.     IF NOT isNowOpen THEN BEGIN
  1553.         IF optionKeyIsDown THEN 
  1554.             okay:= FALSE
  1555.         ELSE WITH gGopherFile DO BEGIN
  1556.             vRefNum:= 0; {! should use something better ...}
  1557.             versnum:= 0; 
  1558.             fType:= kGopherFileType;
  1559.             fName:= kGopherFileName;
  1560.             okay:= (noErr = FSOpen( fName, vRefNum, aRefNum));
  1561.             IF (noErr = FSClose(aRefNum)) THEN ;
  1562.             END;
  1563.         IF (okay) THEN
  1564.             afList:= AppFileToList( gGopherFile) 
  1565.       else
  1566.             okay:= gApplication.ChooseDocument( cOpenGopher, afList);
  1567.         IF (okay) THEN 
  1568.             gApplication.OpenOld( cOpenGopher, afList);
  1569.         TObject(afList):= FreeListIfObject( TList(afList));
  1570.         END;
  1571. END;
  1572.  
  1573.  
  1574. PROCEDURE OpenGopherPrefs;
  1575. VAR aWind    : TGopherPrefs; isNowOpen: boolean;
  1576.  
  1577.     PROCEDURE checkOpenWind( aWind: TWindow);
  1578.     BEGIN
  1579.         IF Member(TObject(aWind), TGopherPrefs) THEN BEGIN 
  1580.             aWind.Select; isNowOpen:= TRUE;
  1581.             END;
  1582.     END;
  1583. BEGIN
  1584.     isNowOpen:= FALSE;
  1585.     gApplication.ForAllWindowsDo(checkOpenWind);
  1586.     IF NOT isNowOpen THEN BEGIN
  1587.         aWind := TGopherPrefs(gViewServer.NewTemplateWindow(kGopherPrefsID, NIL));
  1588.         FailNIL(aWind);          
  1589.         aWind.IGopherPrefs;
  1590.         aWind.ShowReverted;   
  1591.         aWind.Open;  
  1592.         END;
  1593. END;
  1594.  
  1595.  
  1596.  
  1597.  
  1598.  
  1599. { TGopherEditCommand ------------------------------}
  1600.  
  1601.  
  1602. {! DAMN -- this is near duplication of my TSequence GridView handlers
  1603.   -- really want GridView general method that we subclass as needed,
  1604.          this is more code (but less brain work...)
  1605. }
  1606.  
  1607. {$S TGopherEditCommand}
  1608.  
  1609. PROCEDURE TGopherEditCommand.IGopherEditCommand(itsDocument: TGopherDocument; itsCommand: INTEGER);
  1610. VAR fi:            FailInfo;
  1611.      theContext:    TCommandHandler; 
  1612.  
  1613.     PROCEDURE HdlAllocationFailure(error: OSErr; message: LONGINT);
  1614.     BEGIN
  1615.         Free;
  1616.     END;
  1617.  
  1618. BEGIN
  1619.     fSelection:= NIL;
  1620.     fOldList:= NIL;
  1621.     FailNIL( itsDocument);
  1622.     { theContext:    TCommandHandler;}
  1623.     theContext:= itsDocument.fGopherView.GetContext(itsCommand);
  1624.     ICommand(itsCommand, theContext, kCanUndo, kCausesChange, theContext);
  1625.  
  1626.     fGopherDoc := itsDocument; 
  1627.     CatchFailures(fi, HdlAllocationFailure);
  1628.     fSelection := MakeNewRgn;                     
  1629.     fOldList:= TGopherList(fGopherDoc.fGopherList.Clone);
  1630.     FailNIL( fOldList);
  1631.     CopyRgn(fGopherDoc.fGopherView.fSelections, fSelection);
  1632.     Success(fi);
  1633.     
  1634.     fChangesClipboard := itsCommand <> cClear;
  1635.     fCausesChange := itsCommand <> cCopy;
  1636.     fCanUndo := itsCommand <> cCopy;  {?}
  1637. END;
  1638.  
  1639.  
  1640. PROCEDURE TGopherEditCommand.Free; OVERRIDE;
  1641. BEGIN
  1642.     IF (fSelection<>NIL) THEN DisposeRgn(fSelection);
  1643.     fSelection := NIL;
  1644.     IF (fOldList<>NIL) THEN fOldList.Free;
  1645.     fOldList:= NIL;
  1646.     INHERITED Free;
  1647. END;
  1648.  
  1649.  
  1650. PROCEDURE TGopherEditCommand.CopySelection;
  1651. VAR
  1652.         clipDoc        : TGopherDocument;
  1653.         clipView    : TGopherView;
  1654.         
  1655.     PROCEDURE CopyRowToClipboard(aRow: integer);
  1656.     VAR  aGopher: TGopher;
  1657.     BEGIN
  1658.         aGopher:= TGopher(fGopherDoc.fGopherView.GopherAt(aRow).Clone);
  1659.         aGopher.fOwnerList:= clipDoc.fGopherList;
  1660.         clipDoc.fGopherList.InsertLast( aGopher);
  1661.     END;
  1662.  
  1663. BEGIN
  1664.     New(clipDoc);
  1665.     FailNIL(clipDoc);
  1666.     clipDoc.IGopherDocument( NIL, NIL, NIL, NIL);
  1667.     fGopherDoc.fGopherView.EachSelectedRowDo(CopyRowToClipboard);  
  1668.  
  1669.     clipView:= TGopherView( 
  1670.         gViewServer.DoCreateViews(clipDoc, NIL, kGopherViewID, gZeroVPt));
  1671.     FailNIL( clipView);
  1672.     clipView.IGopherView( clipDoc.fGopherList);
  1673.  
  1674.     SELF.ClaimClipboard(clipView);  
  1675. END;
  1676.  
  1677.  
  1678.  
  1679. PROCEDURE TGopherEditCommand.DeleteSelection;
  1680. VAR
  1681.         totalRows: integer;
  1682.         
  1683.     PROCEDURE MarkDelete(aRow: integer);
  1684.     VAR     aGopher : TGopher;
  1685.              vbounds: VRect;
  1686.              jcol, maxcol: integer;
  1687.              aCell: GridCell;
  1688.     BEGIN
  1689.         aGopher:= fGopherDoc.fGopherView.GopherAt(aRow);
  1690.         IF (aGopher<>NIL) THEN BEGIN
  1691.             aGopher.fDeleted:= TRUE;
  1692.             fGopherDoc.fGopherList.AtDelete(aRow); { this should be safe...}
  1693.             
  1694.             fGopherDoc.fGopherView.RowToVRect( aRow, totalRows-aRow+1, vbounds); 
  1695.             fGopherDoc.fGopherView.InvalidateVRect( vbounds);
  1696.             
  1697.             aCell.v:= aRow; maxcol:= fGopherDoc.fGopherView.LastSelectedCell.h;
  1698.             for jcol:= 1 to maxcol do begin
  1699.                 aCell.h:= jcol;
  1700.                 fGopherDoc.fGopherView.SelectCell( aCell, kDontExtend, kDontHighlight, NOT kSelect);
  1701.                 end;
  1702.             END;
  1703.     END;
  1704.  
  1705. BEGIN
  1706.     totalRows:= fOldList.GetSize;
  1707.     fGopherDoc.fGopherView.EachSelectedRowDo(MarkDelete);
  1708.     fGopherDoc.fGopherView.UpdateSize;  
  1709. END;
  1710.  
  1711.  
  1712. PROCEDURE TGopherEditCommand.RestoreSelection;
  1713. VAR  aRow, totalRows: integer;
  1714.     
  1715.     PROCEDURE restoreDeletes(aGopher: TGopher);
  1716.     VAR  vbounds: VRect;
  1717.     BEGIN
  1718.         aRow:= aRow+1;
  1719.         IF (aGopher.fDeleted) THEN BEGIN  
  1720.             aGopher.fDeleted:= FALSE;
  1721.             fGopherDoc.fGopherList.InsertBefore(aRow, aGopher);     
  1722.             
  1723.             fGopherDoc.fGopherView.InsRowBefore( aRow, 1, fGopherDoc.fGopherView.fRowHeight);
  1724.             fGopherDoc.fGopherView.RowToVRect( aRow, totalRows-aRow+1, vbounds); 
  1725.             fGopherDoc.fGopherView.InvalidateVRect( vbounds);
  1726.             END;
  1727.     END;
  1728.  
  1729. BEGIN
  1730.     aRow:= 0;
  1731.     totalRows:= fOldList.GetSize;
  1732.     fOldList.Each( restoreDeletes);
  1733.     fGopherDoc.fGopherView.UpdateSize;  
  1734.     ReSelect; { == fGopherDoc.fGopherView??.ReSelect(fSelection);}
  1735. END;
  1736.  
  1737.  
  1738. PROCEDURE TGopherEditCommand.Commit;
  1739.     PROCEDURE commitDeletes(aGopher: TGopher);
  1740.     BEGIN
  1741.         IF (aGopher<>NIL) & (aGopher.fDeleted) THEN aGopher.Free;  
  1742.     END;
  1743. BEGIN
  1744.     fOldList.Each( commitDeletes);
  1745. END;
  1746.  
  1747. PROCEDURE TGopherEditCommand.ReSelect;
  1748. BEGIN
  1749.     fGopherDoc.fGopherView.SetSelection(fSelection, kDontExtend, kHighlight, kSelect);
  1750. END;
  1751.  
  1752.  
  1753. PROCEDURE TGopherEditCommand.DoIt;
  1754. BEGIN
  1755.     IF fIdentifier <> cClear THEN CopySelection;
  1756.     IF fIdentifier <> cCopy THEN DeleteSelection;
  1757. END;
  1758.  
  1759.  
  1760. PROCEDURE TGopherEditCommand.UndoIt;
  1761. { If the user has changed the selection since this command was created,
  1762.   restore it before Undoing so that the correct cells are affected. }
  1763. BEGIN
  1764.     IF fIdentifier <> cCopy THEN BEGIN
  1765.         RestoreSelection;
  1766.         {- ReSelect;    << see RestoreSelection....}
  1767.         fGopherDoc.fGopherView.ScrollSelectionIntoView(TRUE);
  1768.         END;
  1769. END;
  1770.  
  1771.  
  1772. PROCEDURE TGopherEditCommand.RedoIt;
  1773. { If the user has changed the selection since this command was created,
  1774.   restore it before Redoing so that the correct cells are affected. }
  1775. BEGIN
  1776.     IF fIdentifier <> cCopy THEN BEGIN
  1777.         DeleteSelection;
  1778.         {- ReSelect;     ! NOT After DELETION....}     
  1779.         fGopherDoc.fGopherView.ScrollSelectionIntoView(TRUE);
  1780.         END;
  1781. END;
  1782.  
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791. { TGopherPasteCommand -----------------  }
  1792. {$S TGopherPasteCommand}
  1793.  
  1794.  
  1795. PROCEDURE TGopherPasteCommand.IGopherPasteCommand(itsDocument: TGopherDocument);
  1796. VAR     fi:            FailInfo;
  1797.     theContext:    TCommandHandler;
  1798.  
  1799.     PROCEDURE HdlAllocationFailure(error: OSErr; message: LONGINT);        
  1800.     BEGIN
  1801.         Free;
  1802.     END;
  1803.     
  1804.     PROCEDURE cloneit( aGopher: TGopher);
  1805.     VAR  aRow: integer;
  1806.     BEGIN
  1807.         aRow:= fClipList.GetEqualItemNo(aGopher);
  1808.         aGopher:= TGopher(aGopher.Clone);
  1809.         aGopher.fOwnerList:= fClipList;
  1810.         fClipList.AtPut( aRow, aGopher);
  1811.     END;
  1812.  
  1813. BEGIN
  1814.     { theContext    TCommandHandler;}
  1815.     theContext:= itsDocument.fGopherView.GetContext(cPaste);
  1816.     ICommand(cPaste, theContext, kCanUndo, kCausesChange, theContext);
  1817.  
  1818.     fGopherDoc := itsDocument;
  1819.     CatchFailures(fi, HdlAllocationFailure);
  1820.     fSelection := MakeNewRgn;                            { copy the current selection region }
  1821.     Success(fi);
  1822.     CopyRgn(fGopherDoc.fGopherView.fSelections, fSelection);
  1823.             
  1824.     {- fClipList:= TGopherView(gClipView).fGopherList; }
  1825.     {^^ clone all of this so we don't have mysterious bombs when something trashes clipbd
  1826.         before this command is committed }
  1827.     fClipList:= TGopherList(TGopherView(gClipboardMgr.fClipView).fGopherList.Clone);
  1828.     fClipList.Each( cloneit);
  1829.     
  1830.     fReplacedList:= TGopherList(NewList);
  1831.     FailNIL(fReplacedList);
  1832. END;
  1833.  
  1834.  
  1835. PROCEDURE TGopherPasteCommand.Free; OVERRIDE;
  1836. BEGIN
  1837.     IF fSelection <> NIL THEN DisposeRgn(fSelection);
  1838.     fSelection := NIL;
  1839.     TObject(fClipList) := FreeListIfObject(fClipList); {New since cloned clip list}
  1840.     TObject(fReplacedList) := FreeListIfObject(fReplacedList);
  1841.     INHERITED Free;
  1842. END;
  1843.  
  1844.  
  1845. PROCEDURE TGopherPasteCommand.DoIt;
  1846. VAR  aRow, totalRows: integer;
  1847.         
  1848.     PROCEDURE InsertMarker( aGopher: TGopher);
  1849.     VAR   vbounds: VRect;
  1850.     BEGIN
  1851.         aRow:= aRow+1;
  1852.         {- aGopher:= TGopher(aGopher.Clone);} {? do here or in Commit<<<<  ???}
  1853.         { mark here, fDeleted, then clone in .Commit method}
  1854.         aGopher.fDeleted:= TRUE;  {< this is mark that we Inserted it (not deleted)}
  1855.         
  1856.         fGopherDoc.fGopherList.InsertBefore( aRow, aGopher);
  1857.         
  1858.         fGopherDoc.fGopherView.InsRowBefore( aRow, 1, fGopherDoc.fGopherView.fRowHeight);
  1859.         fGopherDoc.fGopherView.RowToVRect( aRow, totalRows-aRow+1, vbounds); 
  1860.         fGopherDoc.fGopherView.InvalidateVRect( vbounds);
  1861.     END;
  1862.  
  1863. BEGIN            
  1864.     aRow:= fGopherDoc.fGopherView.LastSelectedCell.v;
  1865.     IF aRow=0 THEN aRow:= fGopherDoc.fGopherList.GetSize;
  1866.     totalRows:= fGopherDoc.fGopherList.GetSize + fClipList.GetSize;
  1867.     fClipList.Each(InsertMarker);
  1868.     fGopherDoc.fGopherView.UpdateSize;  
  1869.     {select the pasted cells & scroll into view ?!!}
  1870. END; 
  1871.  
  1872.  
  1873. PROCEDURE TGopherPasteCommand.UndoIt;
  1874. VAR
  1875.         totalRows: integer;
  1876.         
  1877.     PROCEDURE DeleteIfMarked( aGopher: TGopher);
  1878.     VAR     vbounds: VRect;
  1879.              aRow, jcol, maxcol: integer;
  1880.              aCell: GridCell;
  1881.     BEGIN
  1882.         IF (aGopher<>NIL) & (aGopher.fDeleted) THEN BEGIN
  1883.             aGopher.fDeleted:= FALSE;
  1884.             aRow:= fGopherDoc.fGopherList.GetEqualItemNo(aGopher);
  1885.             fGopherDoc.fGopherList.AtDelete(aRow); { is this safe? -- we are in List.Each...}
  1886.             
  1887.             fGopherDoc.fGopherView.RowToVRect( aRow, totalRows-aRow+1, vbounds); 
  1888.             fGopherDoc.fGopherView.InvalidateVRect( vbounds);
  1889.  
  1890.             aCell.v:= aRow; maxcol:= fGopherDoc.fGopherView.LastSelectedCell.h;
  1891.             for jcol:= 1 to maxcol do begin
  1892.                 aCell.h:= jcol;
  1893.                 fGopherDoc.fGopherView.SelectCell( aCell, kDontExtend, kDontHighlight, NOT kSelect);
  1894.                 END;
  1895.             END;
  1896.     END;
  1897.  
  1898. BEGIN
  1899.     totalRows:= fGopherDoc.fGopherList.GetSize;
  1900.     fGopherDoc.fGopherList.Each( DeleteIfMarked);
  1901.     fGopherDoc.fGopherView.UpdateSize;  
  1902. END;
  1903.  
  1904.  
  1905. PROCEDURE TGopherPasteCommand.RedoIt;
  1906. BEGIN
  1907.     DoIt;
  1908. END;
  1909.  
  1910. PROCEDURE TGopherPasteCommand.Commit; OVERRIDE;
  1911.  
  1912.     PROCEDURE commitInserts( aGopher: TGopher);
  1913.     VAR  aRow: integer;
  1914.     BEGIN
  1915.         IF (aGopher.fDeleted) THEN BEGIN
  1916.             aGopher.fDeleted:= FALSE;
  1917.             aRow:= fGopherDoc.fGopherList.GetEqualItemNo(aGopher);
  1918.             aGopher:= TGopher(aGopher.Clone);
  1919.             aGopher.fOwnerList:= fGopherDoc.fGopherList;
  1920.             fGopherDoc.fGopherList.AtPut( aRow, aGopher);
  1921.             END;
  1922.     END;
  1923. BEGIN
  1924.     fGopherDoc.fGopherList.Each( commitInserts);
  1925. END;
  1926.  
  1927. PROCEDURE TGopherPasteCommand.UpdateViews;
  1928. BEGIN
  1929.  
  1930. END;
  1931.